﻿#region Using Declarations

using System;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Linq;
using System.Text;
using Infrastructure.Domain;
using Infrastructure.Persistence;

#endregion

namespace SocialFront.Core.Persistence
{
    public class Repository : IRepository
    {
        private static DbContext Ctx
        {
            get
            {
                return SocialFrontDataContextFactory.GetDataContext();
            }
        }

        #region IRepository Members

        public IQueryable<TEntity> Query<TEntity>() where TEntity : class, IEntity
        {
            return Ctx.Set<TEntity>();
        }

        public void Update<TEntity>(TEntity entity) where TEntity : IEntity 
        {
            // EF handles this.
        }

        public void Insert<TEntity>(TEntity entity) 
            where TEntity : IEntity 
        {
            Ctx.Set(typeof(TEntity)).Add(entity);
        }

        public void Delete<TEntity>(TEntity entity) 
            where TEntity : class, IEntity 
        {
            var obj = Query<TEntity>().FirstOrDefault(x => x.Id == entity.Id);
            if (obj != null)
            {
                Ctx.Set(typeof(TEntity)).Remove(obj);
            }

            // TODO - Play with this to look for a strategy to avoid unnecessary fetches.
            //var obj = Ctx.Entry(entity);
            //if (obj.State == System.Data.EntityState.Detached)
            //{
            //    Ctx.Set(typeof(TEntity)).Attach(obj.Entity);
            //}
            //Ctx.Set(typeof(TEntity)).Remove(obj.Entity);
        }

        public void SaveChanges()
        {
            try
            {
                Ctx.SaveChanges();
            }
            catch (DbEntityValidationException validationException)
            {
                var errors = new StringBuilder();
                
                foreach (var validationError in validationException.EntityValidationErrors.SelectMany(result => result.ValidationErrors))
                    errors.AppendLine(string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage));

                throw new ApplicationException("Validation error(s) -> " + errors, validationException);
            }
        }

        public void Dispose()
        {
            SocialFrontDataContextFactory.RemoveDataContext();
        }

        #endregion
    }
}
